using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using Utility;

public class WeaponController : MonoBehaviour
{
    private PlayerController playerController;
    [Header("手电筒")]
    [SerializeField] GameObject gameObjectFlashlight;
    [Header("枪")]
    [SerializeField] GameObject gameObjectGun;
    [Header("枪口")]
    [SerializeField] Transform gameObjectMuzzle;
    [Header("剑")]
    [SerializeField] GameObject gameObjectSword;
    private Animator animator;
    private AudioSource audioSource;

    private Dictionary<GunType, Gun> GunInfos { get; set; }
    public WeaponType CurrentWeapon { get; private set; }
    public GunType CurrentGunType { get; private set; }

    #region 射击
    private float shootTime;
    public bool Reloading { get; private set; }
    public bool AutoShoot { get; set; }
    public ParticleSystem muzzleFlash;   // 枪口火焰
    public BulletTrail bulletTrail;      // 子弹轨迹
    public ParticleSystem hitEffect;     // 击中效果
    #endregion

    #region Audio Clip
    private AudioClip soundSingleShoot;
    private AudioClip soundAutoShoot;
    private AudioClip soundReload;
    #endregion

    void Start()
    {
        this.playerController = FindFirstObjectByType<PlayerController>();
        this.animator = GetComponent<Animator>();
        this.audioSource = GetComponent<AudioSource>();
        this.GunInfos = new()
        {
            {
                GunType.Burst,
                new()
                {
                    AD = 10.0f,
                    CD = 0.1f,
                    MagazionSize = 50,
                    AmmoCapacity = int.MaxValue,
                    CurrentAmmo = 50,
                    Range = 20,
                    HorizontalRecoil = 0.05f,
                    VerticalRecoil = 0.05f
                }
            },
            {
                GunType.Automatic,
                new()
                {
                    AD = 10.0f,
                    CD = 0.1f,
                    MagazionSize = 100,
                    AmmoCapacity = int.MaxValue,
                    CurrentAmmo = 100,
                    Range = 20,
                    HorizontalRecoil = 0.05f,
                    VerticalRecoil = 0.05f
                }
            },
            {
                GunType.AssaultRifle,
                new()
                {
                    AD = 10.0f,
                    CD = 0.1f,
                    MagazionSize = 100,
                    AmmoCapacity = int.MaxValue,
                    CurrentAmmo = 100,
                    Range = 20,
                    HorizontalRecoil = 0.02f,
                    VerticalRecoil = 0.02f
                }
            }
        };
        this.soundSingleShoot = Resources.Load<AudioClip>("AudioClips/SingleShot");
        this.soundAutoShoot = Resources.Load<AudioClip>("AudioClips/AutoShoot");
        this.soundReload = Resources.Load<AudioClip>("AudioClips/Reload");
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            ChangeWeapon();
            DisplayWeapon();
            this.animator.SetInteger(nameof(WeaponType), (int)this.CurrentWeapon);
        }
    }

    private void ChangeWeapon()
    {
        bool confirm = false;

        foreach (WeaponType weapon in Enum.GetValues(typeof(WeaponType)))
        {
            if (confirm)
            {
                this.CurrentWeapon = weapon;
                return;
            }

            if (this.CurrentWeapon == weapon)
            {
                confirm = true;
            }
        }

        this.CurrentWeapon = WeaponType.Flashlight;
    }

    private void DisplayWeapon()
    {
        switch (this.CurrentWeapon)
        {
            case WeaponType.Flashlight:
                this.gameObjectFlashlight.SetActive(true);
                this.gameObjectGun.SetActive(false);
                this.gameObjectSword.SetActive(false);
                break;
            case WeaponType.Gun:
                this.gameObjectFlashlight.SetActive(false);
                this.gameObjectGun.SetActive(true);
                this.gameObjectSword.SetActive(false);
                this.CurrentGunType = GunType.AssaultRifle;
                break;
            case WeaponType.Sword:
                this.gameObjectFlashlight.SetActive(false);
                this.gameObjectGun.SetActive(false);
                this.gameObjectSword.SetActive(true);
                break;
        }
    }

    public float GetGunCD()
    {
        return this.GunInfos[this.CurrentGunType].CD;
    }

    public int GetCurrentAmmo()
    {
        return this.GunInfos[this.CurrentGunType].CurrentAmmo;
    }

    public void Shoot()
    {
        var cd = this.GetGunCD();
        if (Time.time - this.shootTime > cd
            && this.GetCurrentAmmo() > 0)
        {
            this.shootTime = Time.time;
            var gunInfo = this.GunInfos[this.CurrentGunType];
            gunInfo.CurrentAmmo--;

            #region 闪光特效
            #endregion

            #region 后坐力动画
            var duration = cd / 2.0f - 0.02f; // -0.02以防止动画时间超过CD时间
            var vector3Origin = transform.localPosition;
            var vector3Recoil = new Vector3(transform.localPosition.x + gunInfo.HorizontalRecoil,
                transform.localPosition.y + gunInfo.VerticalRecoil, 0);
            transform.DOLocalMove(vector3Recoil, duration).OnComplete(() =>
            {
                transform.DOLocalMove(vector3Origin, duration);
            });
            #endregion

            #region 音效
            if (this.AutoShoot)
            {
                this.audioSource.PlayOneShot(this.soundAutoShoot);
            }
            else
            {
                this.audioSource.PlayOneShot(this.soundSingleShoot);
            }
            #endregion

            #region 敌人检测
            // 播放枪口火焰
            if (muzzleFlash != null)
            {
                muzzleFlash.transform.position = this.gameObjectMuzzle.position;
                muzzleFlash.Play();
            }

            Vector3 hitPoint;
            Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
            if (Physics.Raycast(this.gameObjectMuzzle.position, this.gameObjectMuzzle.forward,
                out var hitInfo, gunInfo.Range))
            {
                hitPoint = hitInfo.point;
                // 在击中点播放特效
                if (hitEffect != null)
                {
                    hitEffect.transform.position = hitPoint;
                    hitEffect.transform.rotation = Quaternion.LookRotation(hitInfo.normal);
                    hitEffect.Play();
                }
                // 处理击中逻辑
                var collider = hitInfo.collider;
                if (collider.CompareTag(Defines.Zombie))
                {
                    var zombieController = collider.GetComponent<ZombieController>();
                    zombieController.Damage(gunInfo.AD);
                }
            }
            else
            {
                // 如果没有击中，使用最大距离的点
                hitPoint = ray.origin + ray.direction * gunInfo.Range;
                // hitPoint = this.gameObjectMuzzle.forward + this.gameObjectMuzzle.forward * gunInfo.Range;
            }
            // 创建子弹轨迹
            if (bulletTrail != null)
            {
                bulletTrail.CreateTrail(this.gameObjectMuzzle.position, hitPoint);
            }
            #endregion
        }

    }

    /// <summary>
    /// 换弹
    /// </summary>
    public void GunReload()
    {
        /* 此处不可用PlayerController.CurrentAction == ActionStatus.Reload 来判断当前是否在换弹，
            因为ActionStatus.Reload与ActionStatus.Idle是共存的，并且ActionStatus.Idle优先
         */

        if (this.CurrentWeapon == WeaponType.Gun
            && !this.Reloading)
        {
            var gunInfo = this.GunInfos[this.CurrentGunType];
            if (gunInfo.CurrentAmmo < gunInfo.MagazionSize)
            {
                this.Reloading = true;
                this.audioSource.PlayOneShot(this.soundReload);
                StartCoroutine(nameof(GunReloadCoroutine));
            }
        }
    }

    IEnumerator GunReloadCoroutine()
    {
        this.animator.CrossFade("GunReload", 0);
        // TODO 在混合树中播放会混乱，跟播放速度有关
        // this.animatorWeapon.SetFloat(Defines.ActionStatus, (float)ActionStatus.Reload);
        yield return new WaitForSeconds(2.967f);
        this.Reloading = false;
        var gunInfo = this.GunInfos[this.CurrentGunType];
        var ammoCount = 0;
        if (gunInfo.AmmoCapacity == int.MaxValue)
        {
            // 无限子弹
            ammoCount = gunInfo.MagazionSize;
        }
        else
        {
            // 剩余弹药
            var remainingAmmo = gunInfo.AmmoCapacity - gunInfo.MagazionSize;
            if (remainingAmmo > gunInfo.MagazionSize)
            {
                // 弹药充足
                ammoCount = gunInfo.MagazionSize;
                gunInfo.AmmoCapacity = remainingAmmo;
            }
            else
            {
                // 弹药不足，全部填充
                ammoCount = gunInfo.AmmoCapacity;
                gunInfo.AmmoCapacity = 0;
            }
        }
        gunInfo.CurrentAmmo = ammoCount;
    }
    
}
